import 'dart:async';
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart' hide WidgetPaddingX;
import 'package:hotpot/basic/app_colors.dart';
import 'package:hotpot/extensions/data.dart';
import 'package:hotpot/http/http_api.dart';
import 'package:hotpot/models/create_order_req.dart';
import 'package:hotpot/models/floor.dart';
import 'package:hotpot/models/shop_detail.dart';
import 'package:hotpot/models/table_count.dart';
import 'package:hotpot/odoo/odoo_helper.dart';
import 'package:hotpot/pages/order/widgets/confirma_pin_widget.dart';
import 'package:hotpot/route/route_ext.dart';
import 'package:hotpot/route/route_mixin.dart';
import 'package:hotpot/route/routes.dart';
import 'package:hotpot/utils/user_utils.dart';
import 'package:hotpot/widgets/styles/icon_box.dart';
import 'package:hotpot/widgets/styles/num_keyboard.dart';
import 'package:hotpot/widgets/widget_ext.dart';
import 'package:web_socket_channel/io.dart';

import '../../widgets/z_container.dart';

late ShopDetail detail;

void Function()? tableRefresh;

class TablePage extends StatefulWidget {
  const TablePage({super.key});

  @override
  State<TablePage> createState() => _TablePageState();
}

class _TablePageState extends State<TablePage> with ArgMixin {
  // late ShopDetailHrEmployees employees;

  int floorIndex = 0;

  Map<int, TableCount> tableMap = {};
  late int staffId;
  int? tableId;
  late String accessToken;

  // var showStaff = false.obs;
  // var staffId = 0.obs;
  var staffPassword = ''.obs;

  var showCliente = false.obs;
  var clienteCount = ''.obs;
  var showPin = false.obs;

  Timer? timer;

  int currOrderNum = 0;

  FloorTables? currData;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    tableRefresh = () async {
      timer?.cancel();
      timer = Timer(const Duration(milliseconds: 0), () async {
        var data = await HttpApi.getTablesOrderCountChanges(int.parse(detail.posSession!.configId!.first));
        var list = (data.result as List).map((e) => TableCount.fromJson(e)).toList();
        for (var item in list) {
          tableMap[item.id!] = item;
        }
        setState(() {});
      });
    };
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: detail.restaurantFloors?.length ?? 0,
      child: Scaffold(
        backgroundColor: AppColors.baColor,
        body: Stack(
          children: [
            Column(
              children: [
                14.hSizedBox,
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    UserUtils.companyName.text(size: 10, bold: true, color: Colors.black),
                  ],
                ),
                SingleChildScrollView(
                  padding: EdgeInsets.only(top: 11.w),
                  scrollDirection: Axis.horizontal,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ...(detail.restaurantFloors ?? []).map(floorBox),
                    ],
                  ),
                ),
                // staffBox(),
                // const TimeBox().positioned(left: 66, top: 7),
                // const IconBox(Icons.refresh, 25, 22, bgColor: Colors.transparent)
                //     .gestureDetector(onTap: () => tableRefresh?.call())
                //     .positioned(top: 5, right: 40),
                // const IconBox(Icons.person_add_alt_outlined, 25, 22, bgColor: Colors.transparent)
                //     .gestureDetector(onTap: () => Routes.addUser.pushNamed())
                //     .positioned(top: 5, right: 5),
                Builder(
                  builder: (context) {
                    var list = detail.restaurantFloors![floorIndex].tables ?? [];
                    list.sort((a, b) {
                      if (a.name == null || b.name == null) {
                        return 0;
                      } else if (a.name!.length == b.name!.length) {
                        return a.name!.compareTo(b.name!);
                      } else {
                        return a.name!.length - b.name!.length;
                      }
                    });
                    return GridView.builder(
                      padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14).r,
                      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 7,
                        childAspectRatio: 60 / 49,
                        crossAxisSpacing: 7.r,
                        mainAxisSpacing: 7.r,
                      ),
                      itemBuilder: (_, index) => _item(list, index),
                      itemCount: list.length,
                    );
                  },
                ).expanded(),
              ],
            ).positioned(left: 0, right: 0, bottom: 0, top: 0),
            cleenteBox(),
            staffBox(),
            'images/img_back.png'
                .assetImage(width: 10, height: 15)
                .paddingOnly(left: 15, top: 16)
                .gestureDetector(onTap: () => Routes.store.popAndPushNamed())
                .positioned(left: 0, top: 0),
          ],
        ),
      ),
    );
  }

  Widget? _item(List<FloorTables> list, int index) {
    var data = list[index];
    var orderNum = tableMap[data.id]?.orders ?? 0;
    return Stack(
      children: [
        ZContainer(
          borderRadius: BorderRadius.circular(8),
          color: orderNum > 0 ? data.color.color : const Color(0xFFC4C4C4),
        ).positioned(left: 0, right: 0, top: 0, bottom: 0),
        // const IconBox(Icons.person, 8, 8, bgColor: Colors.transparent, color: Colors.white),
        // (data.customerCount ?? 0).text(size: 9, color: Colors.white, bold: true),
        '${data.name}'.text(size: 16, bold: true, color: Colors.white).paddingOnly(right: 3).align(Alignment.bottomRight),
      ],
    ).gestureDetector(onTap: () async {
      currOrderNum = orderNum;
      currData = data;
      showPin.value = true;
    });
  }

  @override
  void loadArg(Map<String, dynamic> arg) {
    // TODO: implement loadArg
    detail = arg['shop'];
    tableMap = arg['table'];
    // staffId = arg['staffId'];
    accessToken = arg['accessToken'];
    initSocket();
  }

  Widget floorBox(Floor e) {
    var index = detail.restaurantFloors!.indexOf(e);
    return Stack(
      children: [
        if (floorIndex == index)
          const Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ZContainer(
                color: Color(0xFFFFDE22),
                height: 1,
                width: 25,
                showShadows: true,
                shadowColor: Color(0xFFFFDE22),
                blurRadius: 3,
                spreadRadius: 1,
                shadowOffset: Offset(0, 0),
              ),
            ],
          ).positioned(left: 0, right: 0, bottom: 5),
        ZContainer(
          height: 17,
          width: 60,
          alignment: Alignment.center,
          radius: 8,
          // color: index == floorIndex ? const Color(0xFF1C1C1C) : Colors.transparent,
          child: e.name.text(color: index == floorIndex ? Colors.black : const Color(0xFFC4C4C4), bold: true, size: 8),
        ).gestureDetector(onTap: () => setState(() => floorIndex = index)),
      ],
    );
  }

  cleenteBox() {
    return Obx(
      () {
        return Row(
          children: [
            const ZContainer(
              height: double.infinity,
              color: Colors.black38,
            ).gestureDetector(onTap: () => showCliente.value = false).expanded(),
            ZContainer(
              width: 186,
              color: const Color(0xFF1F1D2B),
              child: Column(
                children: [
                  const IconBox(Icons.highlight_remove_rounded, 18, 16, bgColor: Colors.transparent)
                      .paddingOnly(top: 8, right: 7)
                      .gestureDetector(onTap: () => showCliente.value = false)
                      .alignRight(),
                  30.hSizedBox,
                  'Cliente'.text(size: 12, color: Colors.white, bold: true),
                  25.hSizedBox,
                  const IconBox(Icons.person_outline, 40, 38, bgColor: Colors.transparent),
                  const SizedBox().expanded(),
                  clienteCount.value.text(size: 15, bold: true, color: Colors.white),
                  17.hSizedBox,
                  NumKeyboard(onTap: (key) {
                    if (key == 'X') {
                      if (clienteCount.value.isNotEmpty) {
                        clienteCount.value = List.generate(
                          clienteCount.value.length - 1,
                          (index) => clienteCount.value[index],
                        ).join();
                      }
                    } else if (key.isEmpty) {
                    } else {
                      clienteCount.value += key;
                    }
                    if (kDebugMode && clienteCount.value.isNotEmpty) {
                      submit();
                    }
                  }),
                  10.hSizedBox,
                  ZContainer(
                    color: const Color(0xFF0022AA),
                    height: 31,
                    radius: 3,
                    alignment: Alignment.center,
                    margin: const EdgeInsets.symmetric(horizontal: 17),
                    child: 'OK'.text(size: 10, bold: true, color: Colors.white),
                  ).gestureDetector(onTap: () => submit()),
                  16.hSizedBox,
                ],
              ),
            ),
          ],
        ).visibility(showCliente.value);
      },
    ).positioned(right: 0, top: 0, bottom: 0, left: 0);
  }

  submit() async {
    var count = int.tryParse(clienteCount.value);
    if (count == null) {
      showToast('请输入就餐人数');
      return;
    }
    var value = await HttpApi.getSessionOrdersByTable(detail.posSession!.id!, tableId!);
    var data = value.result as List;
    var list = data.map((e) => CreateOrderReq.fromJson(e)).toList();
    CreateOrderReq orderData;
    var requiredCate = detail.posCategorys!.where((e) => e.required == true);
    var required = false;
    if (list.isEmpty) {
      var req = CreateOrderReq();
      req.dateOrder = DateTime.now().toString().substring(0, 19);
      req.lines = [];
      req.tableId = tableId;
      req.customerCount = count;
      req.mobileSend = false;
      var value = await HttpApi.createOrder(
        detail.posSession!.id!,
        tableId!,
        staffId,
        detail.posSession!.loginNumber!,
        req.toJson(),
      );
      orderData = CreateOrderReq.fromJson(value.result);
      required = requiredCate.isNotEmpty;
    } else {
      orderData = list.first;
      var productCateIds = <int>[];
      for (var line in orderData.lines ??= []) {
        var product = detail.productProducts!.firstWhere((e) => e.id == line.productId);
        productCateIds.addAll(product.posCategIds ?? []);
      }
      for (var item in requiredCate) {
        var ids = detail.posCategorys!.where((e) => e.parentId?.contains('${item.id}') ?? false).map((e) => e.id!).toList();
        ids.add(item.id!);
        if (ids.indexWhere((e) => productCateIds.contains(e)) == -1) {
          required = true;
          break;
        }
      }
    }
    var table = detail.restaurantFloors![floorIndex].tables!.firstWhere((e) => e.id == tableId);
    showCliente.value = false;
    Routes.requiredBanner.pushNamed(arg: {'data': orderData, 'table': table, 'required': required, 'staffId': staffId});
    // Routes.order.pushNamed(arg: {'data': orderData, 'table': table, 'required': required});
  }

  IOWebSocketChannel? channel;

  void initSocket() async {
    final wsUrl = Uri.parse(OdooHelper.baseWss);
    channel = IOWebSocketChannel.connect(
      wsUrl,
      headers: {
        'Cookie': 'session_id=${OdooHelper.sessionId}',
        'Origin': OdooHelper.baseurl,
        // 'Upgrade': 'websocket',
        // 'Sec-WebSocket-Key': '',
        // 'Sec-WebSocket-Version': '13',
        // 'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
      },
    );

    await channel!.ready;

    channel!.stream.listen((message) {
      print(message);
      var result = jsonDecode(message);
      if (result is List) {
        for (var item in result) {
          if (item is Map) {
            var content = item['message'];
            if (content is Map) {
              var type = content['type'];
              if (type == 'SYNC_ORDERS') {
                tableRefresh?.call();
                // var payload = content['payload'];
                // if (payload is List) {
                //   var list = payload.map((e) => TableCount.fromJson(e)).toList();
                //   for (var item in list) {
                //     tableMap[item.id!] = item;
                //   }
                //   setState(() {});
                //   // showToast('有新订单，请注意!!!');
                //   return;
                // }
              }
            }
          }
        }
      }
    });

    var map = {
      "event_name": "subscribe",
      "data": {
        // "channels": [
        //   "pos_session-${detail.posSession?.id}-${detail.posSession?.accessToken}",
        // ],
        "channels": [accessToken],
        "last": false,
      },
    };
    channel!.sink.add(jsonEncode(map).codeUnits);
  }

  @override
  void dispose() {
    // TODO: implement dispose
    channel?.stream.listen(null);
    channel?.sink.close();
    channel = null;
    timer?.cancel();
    super.dispose();
  }

  staffBox() {
    return Obx(
      () => ConfirmaPinWidget(
        () => showPin.value = false,
        (id) async {
          staffId = id;
          showPin.value = false;
          if (currOrderNum > 0) {
            var value = await HttpApi.getSessionOrdersByTable(detail.posSession!.id!, currData!.id!);
            var dataList = value.result as List;
            var list = dataList.map((e) => CreateOrderReq.fromJson(e)).toList();
            if (list.isNotEmpty) {
              CreateOrderReq orderData = list.first;
              var required = false;
              var requiredCate = detail.posCategorys!.where((e) => e.required == true);
              var productCateIds = <int>[];
              for (var line in orderData.lines ??= []) {
                var product = detail.productProducts!.firstWhere((e) => e.id == line.productId);
                productCateIds.addAll(product.posCategIds ?? []);
              }
              for (var item in requiredCate) {
                var ids =
                    detail.posCategorys!.where((e) => e.parentId?.contains('${item.id}') ?? false).map((e) => e.id!).toList();
                ids.add(item.id!);
                if (ids.indexWhere((e) => productCateIds.contains(e)) == -1) {
                  required = true;
                  break;
                }
              }
              Routes.order.pushNamed(arg: {'data': orderData, 'table': currData!, 'required': required, 'initStaffId': staffId});
              return;
            }
          }
          tableId = currData!.id;
          staffPassword.value = '';
          clienteCount.value = '10';
          submit();
          // showCliente.value = true;
          // staffPassword.value = '';
          // clienteCount.value = '';
        },
        shop: detail,
      ).visibility(showPin.value),
    ).positioned(right: 0, top: 0, bottom: 0, left: 0);
  }
}
